<template>    
    <div class="masks" v-show="!currentValue">
        <div class="gesturePwd" >
            <div class="gesturePwd-box" style="">
                <div class="head">
                    <div class="head-left" @click="closePwd()">
                        隐藏
                    </div>
                    <div class="head-cont">{{title?title:'验证手势密码'}}</div>
                    <div class="head-left"></div>
                </div>
                <div class="head-sub">
                    <h4 ref="gestureTitle" class="gestureTitle" >请输入手势密码</h4>
                </div>
                <div @click="updatePassword()">重置密码(测试用；后面去掉)</div>
                <!-- <a ref="updatePassword" style="position: absolute;left: 5px;top: 50px;color:#000;font-size: 13px;display:block;" @click="updatePassword()">重置密码</a> -->
                <!-- <a ref="updatePassword" style="position: absolute;right: 5px;top: 50px;color:#000;font-size: 13px;display:block;" @click="closePwd()">关闭</a> -->
              <canvas ref="canvas" style="background-color:#fff; display: inline-block; width: 350px; height: 350px;"></canvas>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    props: {
        value: {
          type: Boolean,
          default: false
        },
        title: {
            type: String,
            default: ''
        },
        pwdnumber: {
          type: String,
          default: ''
        },
        isedit: {
          type: Boolean,
          default: false
        },
    },
  data() {
    return {
      currentValue: false,
      ctx:'',
      width:0,
      height:0,
      devicePixelRatio:0,
      chooseType : '',
      r :'',// 公式计算
      lastPoint: [],
      arr : [],
      restPoint :[],
      pswObj:{step:2},
      canvas:'',
      pwderr:true, // 密码错误提示
      pwdsucc:true, // 密码成功提示
    }
  },
  watch: {
    value: {
      handler: function (val) {
        this.currentValue = val
      },
      immediate: true
    },
    currentValue (val) {
      this.$emit(val ? 'on-show' : 'on-hide')
      this.$emit('input', val)
    }
  },
  created () {
    if (typeof this.value !== 'undefined') {
      this.currentValue = this.value
    }
  },
  mounted() {
      this.setChooseType(3);
  },
  methods: {
    closePwd () {
        console.log('关闭界面');
        this.currentValue = false;
    },
    H5lock (obj){
        this.height = obj.height;
        this.width = obj.width;
        this.chooseType = Number(window.localStorage.getItem('chooseType')) || obj.chooseType;
        this.devicePixelRatio = window.devicePixelRatio || 1;
    },
    drawCle (x, y) { // 初始化解锁密码面板 小圆圈
        this.ctx.strokeStyle = '#3D80CD';//密码的点点默认的颜色
        this.ctx.lineWidth = 2;
        this.ctx.beginPath();
        this.ctx.arc(x, y, this.r, 0, Math.PI * 2, true);
        this.ctx.closePath();
        this.ctx.stroke();
    },
    drawPoint (style) { // 初始化圆心
        for (var i = 0 ; i < this.lastPoint.length ; i++) {
            this.ctx.fillStyle = style;
            this.ctx.beginPath();
            this.ctx.arc(this.lastPoint[i].x, this.lastPoint[i].y, this.r / 2.5, 0, Math.PI * 2, true);
            this.ctx.closePath();
            this.ctx.fill();
        }
    },
    drawStatusPoint (type) { // 初始化状态线条
        for (var i = 0 ; i < this.lastPoint.length ; i++) {
            this.ctx.strokeStyle = type;
            this.ctx.beginPath();
            this.ctx.arc(this.lastPoint[i].x, this.lastPoint[i].y, this.r, 0, Math.PI * 2, true);
            this.ctx.closePath();
            this.ctx.stroke();
        }
    },
    drawLine (style, po, lastPoint) {//style:颜色 解锁轨迹
        this.ctx.beginPath();
        this.ctx.strokeStyle = style;
        this.ctx.lineWidth = 3;
        this.ctx.moveTo(this.lastPoint[0].x, this.lastPoint[0].y);

        for (var i = 1 ; i < this.lastPoint.length ; i++) {
            this.ctx.lineTo(this.lastPoint[i].x, this.lastPoint[i].y);
        }
        this.ctx.lineTo(po.x, po.y);
        this.ctx.stroke();
        this.ctx.closePath();

    },
    createCircle () {// 创建解锁点的坐标，根据canvas的大小来平均分配半径;arr
        var n = this.chooseType;
        var count = 0;
        this.r = this.ctx.canvas.width / (2 + 4 * n);// 公式计算
        this.lastPoint = [];
        this.arr = [];
        this.restPoint = [];
        var r = this.r;
        for (var i = 0 ; i < n ; i++) {
            for (var j = 0 ; j < n ; j++) {
                count++;
                var obj = {
                    x: j * 4 * r + 3 * r,
                    y: i * 4 * r + 3 * r,
                    index: count
                };
                this.arr.push(obj);
                this.restPoint.push(obj);
            }
        }
        this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);

        for (var i = 0 ; i < this.arr.length ; i++) {
            this.drawCle(this.arr[i].x, this.arr[i].y);
           
        }

        //return arr;
    },
    getPosition (e) {// 获取touch点相对于canvas的坐标
        var rect = e.currentTarget.getBoundingClientRect();
        var po = {
            x: (e.touches[0].clientX - rect.left)*this.devicePixelRatio,
            y: (e.touches[0].clientY - rect.top)*this.devicePixelRatio
          };
        return po;
    },
    update(po) {// 核心变换方法在touchmove时候调用
        this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);

        for (var i = 0 ; i < this.arr.length ; i++) { // 每帧先把面板画出来
            this.drawCle(this.arr[i].x, this.arr[i].y);
        }
        this.drawPoint('#3786E1');// 每帧花轨迹
        this.drawStatusPoint('#3786E1');// 每帧花轨迹
        this.drawLine('#3786E1',po , this.lastPoint);// 每帧画圆心
        //1.检测手势移动的位置是否处于下一个圆内
        //2.如果处于圆内则画圆
        //3.已经划过实心圆的圆  无需重复检测
        for (var i = 0 ; i < this.restPoint.length ; i++) {
            if (Math.abs(po.x - this.restPoint[i].x) < this.r && Math.abs(po.y - this.restPoint[i].y) < this.r) {
                this.drawPoint(this.restPoint[i].x, this.restPoint[i].y);
                this.lastPoint.push(this.restPoint[i]);
                //上面是找到画过内圆的 大圆  然后从restPoint中删除掉这个
                this.restPoint.splice(i, 1);
                break;
            }
        }

    },
    checkPass (psw1, psw2) {// 检测密码
        var p1 = '',
        p2 = '';
        for (var i = 0 ; i < psw1.length ; i++) {
            p1 += psw1[i].index + psw1[i].index;
        }
        for (var i = 0 ; i < psw2.length ; i++) {
            p2 += psw2[i].index + psw2[i].index;
        }
        return p1 === p2;
    },
    storePass (psw) {// touchend结束之后对密码和状态的处理
        if(psw.length<5){
            this.$refs.gestureTitle.innerHTML = '至少连接5个点,请重新绘制';
            this.$refs.gestureTitle.style.color = "#FE3726";
            return;
        }
        // this.pswObj.step == 1为绑定是否成功；this.pswObj.step == 2验证是否成功；this.pswObj.step == undefied再次绘制验证
        if (this.pswObj.step == 1) {//绘制密码
            if (this.checkPass(this.pswObj.fpassword, psw)) {
                this.pswObj.step = 2;
                this.pswObj.spassword = psw;
                this.$refs.gestureTitle.innerHTML = '密码保存成功';
                console.log("提示：绑定成功；回到状态a")  
                this.$emit('pwderr',{pwdsucc:this.pwdsucc})
                this.currentValue = false;

                this.drawStatusPoint('#2CFF26');
                this.drawPoint('#2CFF26');
                
                window.localStorage.setItem('passwordxx', JSON.stringify(this.pswObj.spassword));
                window.localStorage.setItem('chooseType', this.chooseType);
            } else {
                var gestureTitle = this.$refs.gestureTitle;
                gestureTitle.innerHTML = '两次密码不一致,请重新绘制';
                gestureTitle.style.color = "#FE3726";
                setTimeout(function(){
                    gestureTitle.innerHTML = '请绘制新的手势密码';
                    gestureTitle.style.color = "#87888a";
                }, 1000)
                this.drawStatusPoint('red');
                this.drawPoint('red');
                delete this.pswObj.step;
            }
        } else if (this.pswObj.step == 2) {//解锁密码
            if (this.checkPass(this.pswObj.spassword, psw)) {
                if(this.$route.query.title == '修改手势密码'){
                    this.updatePassword (); // 修改密码
                    var gestureTitle = this.$refs.gestureTitle;
                    gestureTitle.style.color = "#333";
                    gestureTitle.innerHTML = '请绘制新的手势密码';
                    
                }else{
                    var gestureTitle = this.$refs.gestureTitle;
                    gestureTitle.style.color = "#2CFF26";
                    gestureTitle.innerHTML = '解锁成功';
                    this.drawStatusPoint('#2CFF26');//小点点外圈高亮
                    this.drawPoint('#2CFF26');
                    this.drawLine('#2CFF26',this.lastPoint[this.lastPoint.length-1] , this.lastPoint);// 每帧画圆心
                    this.closePwd();
                    this.$emit('pwderr',{pwdsucc:this.pwdsucc,pwderr:false}) // pwdsucc手势成功；pwderr谷歌成功
                }
            } else if (psw.length < 5) {
                this.drawStatusPoint('red');
                this.drawPoint('red');
                this.drawLine('red',this.lastPoint[this.lastPoint.length-1] , this.lastPoint);// 每帧画圆心
                var gestureTitle = this.$refs.gestureTitle;
                gestureTitle.style.color = "#FE3726";
                gestureTitle.innerHTML = '至少连接5个点,请重新输入';

            } else {
                // 输入的次数由后端判断返回;this.pwdnumber后端传的次数
                if(this.pwdnumber>0){
                    this.drawStatusPoint('red');
                    this.drawPoint('red');
                    this.drawLine('red',this.lastPoint[this.lastPoint.length-1] , this.lastPoint);// 每帧画圆心
                    var gestureTitle = this.$refs.gestureTitle;
                    gestureTitle.style.color = "#FE3726";
                    gestureTitle.innerHTML = '密码错误，您还可以输入'+this.pwdnumber+'次';
                }else{
                    var gestureTitle = this.$refs.gestureTitle;
                    gestureTitle.style.color = "#FE3726";
                    gestureTitle.innerHTML = '多次输入错误,请三小时后再试-----';
                    // this.pwderr = true;//错误弹框
                    this.$emit('pwderr',{pwderr:this.pwderr})
                }
            }
        } else {
            this.pswObj.step = 1;
            this.pswObj.fpassword = psw;
            this.$refs.gestureTitle.innerHTML = '请再次绘制手势密码';
        }
    },
    makeState () {
        if (this.pswObj.step == 2) {
            // this.$refs.updatePassword.style.display = 'block';
            var gestureTitle = this.$refs.gestureTitle;
            gestureTitle.style.color = "#87888a";
            gestureTitle.innerHTML = '请解锁手势密码';
        } else if (this.pswObj.step == 1) {
            // this.$refs.updatePassword.style.display = 'none';
        } else {
            // this.$refs.updatePassword.style.display =  'block';
            // this.$refs.updatePassword.style.display  = 'block';
        }
    },
    setChooseType (type){
        this.chooseType = type;
        this.init();
    },
    updatePassword (){
        window.localStorage.removeItem('passwordxx');
        window.localStorage.removeItem('chooseType');
        this.pswObj = {};
        this.$refs.gestureTitle.innerHTML = '绘制解锁图案';
        this.reset();
    },
    initDom (){   
        this.chooseType = Number(window.localStorage.getItem('chooseType')) || 3;
        this.devicePixelRatio = window.devicePixelRatio || 1;
        var canvas = this.$refs.canvas;
        var width = this.width || 350;
        var height = this.height || 350;
        // 高清屏锁放
        canvas.style.width = width + "px";
        canvas.style.height = height + "px";
        canvas.height = height * this.devicePixelRatio;
        canvas.width = width * this.devicePixelRatio;
    },
    init () {
        this.initDom();
        this.pswObj = window.localStorage.getItem('passwordxx') ? {
            step: 2,
            spassword: JSON.parse(window.localStorage.getItem('passwordxx'))
        } : {};
        this.lastPoint = [];
        this.makeState();
        this.touchFlag = false;
        this.canvas = this.$refs.canvas;
        this.ctx = this.canvas.getContext('2d');
        this.createCircle();
        this.bindEvent();
    },
    reset () {
        this.makeState();
        this.createCircle();
    },
    bindEvent () {
        var self = this;
        this.canvas = this.$refs.canvas;
        this.canvas.addEventListener("touchstart", function (e) {
            e.preventDefault();// 某些android 的 touchmove不宜触发 所以增加此行代码
             var po = self.getPosition(e); // 获取鼠标位置
            //  debugger;//判断条件 触发点与圆心的位置到最左端的绝对值是否小于r   是的话就在圆内
             for (var i = 0 ; i < self.arr.length ; i++) {
                if (Math.abs(po.x - self.arr[i].x) < self.r && Math.abs(po.y - self.arr[i].y) < self.r) {
                    self.touchFlag = true;
                    self.drawPoint(self.arr[i].x,self.arr[i].y);
                    self.lastPoint.push(self.arr[i]); // 密码对x,y,index
                    self.restPoint.splice(i,1);
                    break;
                }
             }
         }, false);
         this.canvas.addEventListener("touchmove", function (e) { // 画圆和画线
            if (self.touchFlag) {
                self.update(self.getPosition(e));
            }
         }, false);
         this.canvas.addEventListener("touchend", function (e) {
             if (self.touchFlag) {
                 self.touchFlag = false;
                 self.storePass(self.lastPoint);
                //  setTimeout(function(){
                    self.reset();
                // }, 1000);
             }
         }, false);
      }
  }
}
</script>

<style lang="less" scoped>
.masks {
    text-align: center;
    position: fixed;
    z-index: 0;
    top: 0;
    right: 0;
    left: 0;
    bottom: 0;
    background: #fff;
}
.gesturePwd{
    position: fixed;
    z-index: 0;
    width: 100%;
    height:100%;
    top: 50%;
    left: 50%;
    -webkit-transform: translate(-50%,-50%);
    transform: translate(-50%,-50%);
    background-color: #666;
    text-align: center;
    border-radius: 3px;
    overflow: hidden;
    background-color: #fff;
}
.gesturePwd-box{
    position: absolute;
    top:0;
    left:0;
    right:0;
    bottom:0;
}
.head {
    width: 100%;
    height: 60px;
    line-height: 60px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-direction: row;
}
.head-left {
    width: 50px;
    height: 60px;
    line-height: 60px;
}
.head-cont {
    font-size:16px;
    font-weight:bold;
    color:#333;
}
.head-sub {
    margin: 40px auto;
}

.gestureTitle {
    font-size:14px;
    font-weight:500;
    color:rgba(51,51,51,1);
    padding-top: 10px;
}
</style> 
